#pragma once
#include "omelette.hpp"

class Planner {
public:

	// Plan returns the next operation to perform.
	// Nop means to finish the simulation, which
	// cannot be performed unless the agent has
	// arrived at a goal state.
	virtual omelette::Op plan(const omelette::State&) = 0;
};

class Oracle : public Planner {
public:
	Oracle(const omelette::State&);
	virtual omelette::Op plan(const omelette::State&);

private:
	std::vector<omelette::Op> ops;
};

class Hindsight : public Planner {
public:
	Hindsight(unsigned int nsamp);
	virtual omelette::Op plan(const omelette::State&);

private:
	unsigned int nsamp;
};


// Handmade is a hand-made controller that puts eggs
// in bowl 0 and smells/cleans until it has a good egg.  Then
// it puts eggs in bowl 1 and smells/cleans until it has a good
// egg, then it pours into bowl 0.  Repeat until done.
class Handmade : public Planner {
public:
	Handmade() : state(Grab), stillzero(true) { }
	virtual omelette::Op plan(const omelette::State&);

private:
	enum {
		Grab, BreakSmell, Pour,
	} state;

	bool stillzero;
};

// Sim simulates the omelette world with the given
// initial state.
void sim(const omelette::State&, Planner*);